package com.dragon.english_practice_back.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dragon.english_practice_back.controller.dto.WordBookDto;
import com.dragon.english_practice_back.entity.WordBook;
import com.dragon.english_practice_back.entity.Words;
import com.dragon.english_practice_back.reponse.Result;
import com.dragon.english_practice_back.service.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/word")
@Slf4j
@AllArgsConstructor
public class WordController {
    AuthenticationUtil authenticationUtil;
    WordsService wordsService;
    WordBookService wordBookService;
    TableAndColumnNameVerifyService tableAndColumnNameVerifyService;
    WordScheduleService wordScheduleService;

    // 分页获取单词书
    @PreAuthorize("hasRole('ROLE_USER')")
    @GetMapping("/getWordBookList")
    public Result<Page<WordBook>> getWordBookList(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "20") Integer pageSize) {
        // 使用mybatis的page分页
        Page<WordBook> page = new Page<>(pageNum, pageSize);
        // 获取公共的单词书
        Page<WordBook> wordBookPage = wordBookService.page(page, new QueryWrapper<WordBook>()
                .select("id", "book_name", "creator_id", "create_date", "is_public")
                .eq("is_public", 1)
                .orderByAsc("create_date")
        );
        return Result.ok("word books", wordBookPage);
    }

    // 分页获取单词书内的单词
    @PreAuthorize("hasRole('ROLE_USER')")
    @GetMapping("/getWordList")
    public Result<Object> getWordList(@RequestParam Integer wordBookId,
                                           @RequestParam(defaultValue = "1") Integer pageNum,
                                           @RequestParam(defaultValue = "20") Integer pageSize,
                                           @RequestParam(defaultValue = "id") String orderBy,
                                           @RequestParam(defaultValue = "asc") String order) {
        // 检查orderBy和order是否合法
        if (!tableAndColumnNameVerifyService.verifyColumnName("words", orderBy)){
            return Result.no("orderBy is not valid", tableAndColumnNameVerifyService.getAllColumnNames("words"));
        }
        if (!order.equals("asc") && !order.equals("desc")){
            return Result.no("order is not valid", List.of("asc", "desc"));
        }
        // 使用mybatis的page分页
        Page<Words> page = new Page<>(pageNum, pageSize);
        // 设置排序
        if (order.equals("desc")) page.setOrders(List.of(OrderItem.desc(orderBy)));
        else page.setOrders(List.of(OrderItem.asc(orderBy)));
        // 根据单词书id获取单词
        Page<Words> wordsPage = wordsService.page(page, new QueryWrapper<Words>()
                .select("id", "word", "meaning", "book_id")
                .eq("book_id", wordBookId)
                .orderByAsc("id")
        );

        return Result.ok("words", wordsPage);
    }

    // 获取单词书内的单词，带熟练度
    @PreAuthorize("hasRole('ROLE_USER')")
    @GetMapping("/getWordListWithProficiency")
    public Result<Object> getWordListWithProficiency(@RequestParam Integer wordBookId,
                                                     @RequestParam(defaultValue = "1") Integer pageNum,
                                                     @RequestParam(defaultValue = "20") Integer pageSize,
                                                     @RequestParam(defaultValue = "id") String orderBy,
                                                     @RequestParam(defaultValue = "asc") String order
    ) {
        // 检查orderBy和order是否合法
        if (!tableAndColumnNameVerifyService.verifyColumnName("words", orderBy) &&
            !tableAndColumnNameVerifyService.verifyColumnName("word_proficiency", orderBy)){
            ArrayList<String> columnNames = new ArrayList<>();
            columnNames.addAll(tableAndColumnNameVerifyService.getAllColumnNames("words"));
            columnNames.addAll(tableAndColumnNameVerifyService.getAllColumnNames("word_proficiency"));
            return Result.no("orderBy is not valid", columnNames);
        }
        if (!order.equals("asc") &&!order.equals("desc")){
            return Result.no("order is not valid", List.of("asc", "desc"));
        }

        // 根据单词书id获取单词
        Page<Map<String, Object>> page = new Page<>(pageNum, pageSize);
        // 设置排序
        if (order.equals("desc")) page.setOrders(List.of(OrderItem.desc(orderBy)));
        else page.setOrders(List.of(OrderItem.asc(orderBy)));
        Page<Map<String, Object>> wordsPage = wordsService.getWordsWithProficiency(page, wordBookId);

        return Result.ok("words", wordsPage);
    }

    // 获取正在学习的单词书
    @PreAuthorize("hasRole('ROLE_USER')")
    @GetMapping("/getLearningWordBook")
    public Result<Object> getLearningWordBook() {
        List<WordBook> wordBookList = wordBookService.getLearningWordBook(authenticationUtil.id());
        return Result.ok("word books", Map.of("records", wordBookList));
    }

    // 获取学习过的单词书
    @PreAuthorize("hasRole('ROLE_USER')")
    @GetMapping("/getLearnedWordBook")
    public Result<Object> getLearnedWordBook() {
        List<WordBook> wordBookList = wordBookService.getLearnedWordBook(authenticationUtil.id());
        return Result.ok("word books", Map.of("records", wordBookList));
    }

    // 获取学习状态
    @PreAuthorize("hasRole('ROLE_USER')")
    @GetMapping("/getLearnStatus")
    public Result<Object> getLearnStatus(@RequestParam Integer wordBookId) {
        Map<String, Boolean> status = wordBookService.getBookStatus(authenticationUtil.id(), wordBookId);
        return Result.ok("learn status", status);
    }

    // 学习单词书
    @PreAuthorize("hasRole('ROLE_USER')")
    @PostMapping("/learnWordBook")
    public Result<Object> learnWordBook(@RequestBody WordBookDto wordBookDto) {
        if (wordBookService.learnWordBook(authenticationUtil.id(), wordBookDto.getWordBookId())) {
            return Result.ok("learn word book", Map.of("wordBookId", wordBookDto.getWordBookId()));
        }
        return Result.no("cannot learn that word book", Map.of("wordBookId", wordBookDto.getWordBookId()));
    }

    // 取消学习单词书
    @PreAuthorize("hasRole('ROLE_USER')")
    @PostMapping("/cancelLearnWordBook")
    public Result<Object> cancelLearnWordBook(@RequestBody WordBookDto wordBookDto) {
        if (wordBookService.unlearnWordBook(authenticationUtil.id(), wordBookDto.getWordBookId())) {

            return Result.ok("cancel learn word book", Map.of("wordBookId", wordBookDto.getWordBookId()));
        }
        return Result.no("cannot cancel learn that word book", Map.of("wordBookId", wordBookDto.getWordBookId()));
    }

    // 删除学习记录
    @PreAuthorize("hasRole('ROLE_USER')")
    @DeleteMapping("/deleteLearnRecord")
    public Result<Object> deleteLearnRecord(@RequestParam Integer wordBookId) {
        if (wordBookService.deleteLearningRecord(authenticationUtil.id(), wordBookId)) {
            return Result.ok("delete learn record", Map.of("wordBookId", wordBookId));
        }
        return Result.no("cannot delete learn record", Map.of("wordBookId", wordBookId));
    }

    // 询问是否还有可学习的单词
    @PreAuthorize("hasRole('ROLE_USER')")
    @GetMapping("/hasLearnableWord")
    public Result<Object> hasLearnableWord() {
        boolean hasLearnableWord = wordScheduleService.hasWordsToLearn(authenticationUtil.id());
        if (hasLearnableWord) {
            return Result.ok("has learnable word", Map.of("hasLearnableWord", hasLearnableWord));
        }
        return Result.ok("not has learnable word", Map.of("hasLearnableWord", hasLearnableWord));
    }

    // 获取今日单词学习计划
    @PreAuthorize("hasRole('ROLE_USER')")
    @GetMapping("/getTodayWordSchedule")
    public Result<Object> getTodayWordSchedule() {
        List<Map<String, Object>> todayWordSchedule = wordScheduleService.getTodayWordSchedule(authenticationUtil.id());
        return Result.ok("get today word schedule", Map.of("records", todayWordSchedule));
    }

    // 手动更新数据redis的数据到mysql中
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @PostMapping("/updateToDatabase")
    public Result<Object> updateToDatabase() {
        wordScheduleService.updateToDatabase();
        return Result.ok("update to database", null);
    }

    // 清空单词计划
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @DeleteMapping("/clearWordSchedule")
    public Result<Object> clearWordSchedule() {
        wordScheduleService.clearWordSchedule();
        return Result.ok("clear word schedule", null);
    }


}
